/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.web.servlet.view.freemarker;

import java.io.IOException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.martinimix.context.support.MartiniMixMacroRequestContext;
import net.martinimix.domain.content.ContentNotFoundException;
import net.martinimix.service.content.BlueMartiniContentService;
import net.martinimix.service.content.ContentService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.view.freemarker.FreeMarkerView;

import com.bluemartini.htmlapp.Content;

import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Provides a Martini Mix environment aware FreeMarker view.
 * 
 * @author Scott Rossillo
 *
 */
public class FreeMarkerMartiniMixView extends FreeMarkerView {
	
	private static final Log log = LogFactory.getLog(FreeMarkerMartiniMixView.class);
	
	private static final String martiniMixMacroRequestContextAttribute = "martiniMixMacroRequestContext";
	
	private ContentService contentService;
	private String baseContentPath;

	/**
	 * Creates a new FreeMarker Martini Mix view.
	 */
	public FreeMarkerMartiniMixView() {
		super();
		// assign a reasonable default content path
		baseContentPath = "/Content/view/";
	}
	
	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.view.AbstractUrlBasedView#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		if(contentService == null) {
			// TODO: should we force content service to be set by DI?
			contentService = new BlueMartiniContentService();
		}
	}

	/**
	 * Exposes the Martini Mix helpers assigned to this view.
	 * 
	 * @see FreeMarkerView#getUrl()
	 * @see FreeMarkerView#exposeHelpers(java.util.Map, javax.servlet.http.HttpServletRequest)
	 */
	protected void exposeHelpers(Map model, HttpServletRequest request)
			throws Exception {
		
		super.exposeHelpers(model, request);
		Content templateContent = this.getTemplateContent();
		
		if(log.isDebugEnabled()) {
			log.debug("Adding template content object [" + templateContent.getPath() + "] to model.");
		}
		
		model.put("templateContent", templateContent);
		model.put(
				martiniMixMacroRequestContextAttribute, 
				new MartiniMixMacroRequestContext(this.getMessageSourceAccessor(), request));
	}
	

	/* (non-Javadoc)
	 * @see org.springframework.web.servlet.view.freemarker.FreeMarkerView#processTemplate(freemarker.template.Template, java.util.Map, javax.servlet.http.HttpServletResponse)
	 */
	protected void processTemplate(Template template, Map model,
			HttpServletResponse response) throws IOException, TemplateException {

		MartiniMixMacroRequestContext ctx = 
			(MartiniMixMacroRequestContext) model.get(martiniMixMacroRequestContextAttribute);
		
		if(ctx != null) {
			ctx.setResponse(response);
		}
		
		super.processTemplate(template, model, response);
	}
	
	/**
	 * Returns the content path for this template.
	 * 
	 * @return the path to the <code>Content</code> for this template
	 * 
	 * @see #setBaseContentPath(String)
	 * @see #getUrl()
	 */
	protected String getTemplateContentPath() {
		
		return this.getBaseContentPath() + this.getUrl();
	}
	
	/**
	 * Returns the Blue Martini content object for this template.
	 * 
	 * @return the <code>Content</code> for this template
	 * 
	 * @throws ContentNotFoundException if the content object represented by
	 * this template cannot be found
	 */
	protected Content getTemplateContent() throws ContentNotFoundException {
		
		return contentService.findContent(this.getTemplateContentPath());
	}

	/**
	 * Returns the base FreeMarker content path.
	 * 
	 * @return the base content path for FreeMarker templates
	 */
	public String getBaseContentPath() {
		return baseContentPath;
	}

	/**
	 * Sets the base content path for FreeMarker views.
	 * 
	 * @param baseContentPath the base content path for FreeMarker views
	 */
	public void setBaseContentPath(String baseContentPath) {
		this.baseContentPath = baseContentPath;
	}
}
